package problem;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Set;

import core.ObjectiveTarget;
import core.Result;

public class Sharpe extends PortfolioProblem {

	private double beta[];
	private double riskFreeRates[];
	private double market_risk;
	private double market_index;

	public Sharpe() {
		this.name = "Sharpe";
		this.restLowerBounds = 0;
		this.restUpperBounds = 1;
		this.firstLowerBounds = new double[0];
		this.firstUpperBounds = new double[0];
		this.objectiveTargets = new ObjectiveTarget[2];
		this.objectiveTargets[0] = ObjectiveTarget.MINIMIZE;
		this.objectiveTargets[1] = ObjectiveTarget.MAXIMIZE;

	}

	public void loadData(FileReader fr) throws IOException {
		// czyta plik w formacie
		// linia z nazwami papierow
		// linia z oprocentowaniem papieru wolnym od ryzyka
		// linia z betami
		// linia z kursami z ostatniego dnia danych analizowanych
		// linia z kursami rzeczywistymi dla dni przewidywanych
		// linia z market risk
		// linia z przewidywaną procentową zmianą indeksu giełdowego

		BufferedReader br = new BufferedReader(fr);
		// linia z nazwami papierow
		String line = br.readLine();
		String[] ratestr = line.split("\t");
		names = new String[ratestr.length];
		int i = 0;
		try {
			while (true) {
				names[i] = ratestr[i];
				i++;
			}
		} catch (IndexOutOfBoundsException iex) {
			//
		}

		// linia z oprocentowaniem papieru wolnym od ryzyka
		if ((line = br.readLine()) == null) {
			throw new IOException();
		}
		ratestr = line.replace(',', '.').split("\t");
		riskFreeRates = new double[ratestr.length];
		i = 0;
		try {
			while (true) {
				riskFreeRates[i] = Double.parseDouble(ratestr[i]);
				i++;
			}
		} catch (NumberFormatException ex) {
			// zle dane w pliku
			throw new IOException();
		} catch (IndexOutOfBoundsException iex) {
			//
		}

		// linia z betami
		if ((line = br.readLine()) == null) {
			throw new IOException();
		}
		String[] betastr = line.replace(',', '.').split("\t");
		beta = new double[betastr.length];
		i = 0;
		try {
			while (true) {
				beta[i] = Double.parseDouble(betastr[i]);
				i++;
			}
		} catch (NumberFormatException ex) {
			// zle dane w pliku
			throw new IOException();
		} catch (IndexOutOfBoundsException iex) {
			//
		}
		
		
		// linia z wartosciami akcji w momencie analizy
		if ((line = br.readLine()) == null) {
			throw new IOException();
		}
		ratestr = line.replace(',', '.').split("\t");
		value = new double[ratestr.length];
		i = 0;
		try {
			while (true) {
				value[i] = Double.parseDouble(ratestr[i]);
				i++;
			}
		} catch (NumberFormatException ex) {
			// zle dane w pliku
			throw new IOException();
		} catch (IndexOutOfBoundsException iex) {
			//
		}
		// linia z kursami rzeczywistymi dla dni przewidywanych
		if ((line = br.readLine()) == null) {
			throw new IOException();
		}
		ratestr = line.replace(',', '.').split("\t");
		realValues = new double[ratestr.length];
		i = 0;
		try {
			while (true) {
				realValues[i] = Double.parseDouble(ratestr[i]);
				i++;
			}
		} catch (NumberFormatException ex) {
			// zle dane w pliku
			throw new IOException();
		} catch (IndexOutOfBoundsException iex) {
			//
		}

		// linia z ryzykiem
		if ((line = br.readLine()) == null) {
			throw new IOException();
		}
		try {

			market_risk = Double.parseDouble(line.replace(',', '.'));
		} catch (NumberFormatException ex) {
			// zle dane w pliku
			throw new IOException();
		}

		// linia z przewidywaną procentową zmianą wartości indeksu
		if ((line = br.readLine()) == null) {
			throw new IOException();
		}
		try {
			market_index = Double.parseDouble(line.replace(',', '.'));
		} catch (NumberFormatException ex) {
			// zle dane w pliku
			throw new IOException();
		}
		this.predictions = new double[names.length];

	}

	public int getProblemSize() {
		if (names != null)
			return names.length;
		return -1;
	}

	@Override
	public double[] calculate(double[] genotype) {
		genotype = normalize(genotype);
		double predicted_return_rate = 0.;
		double predicted_risk = 0.;
		try {
			int i = 0;
			while (true) {
				predicted_return_rate += genotype[i]
						* (this.predictions[i] = this.riskFreeRates[i]
								+ market_index * this.beta[i]);
				predicted_risk += genotype[i] * Math.abs(this.beta[i]);
				i++;
			}

		} catch (Exception e) {
			predicted_risk = predicted_risk * market_risk * market_risk;
		}

		double[] result = new double[2];
		result[0] = predicted_risk;
		result[1] = predicted_return_rate;
		return result;
	}

	@Override
	public String getOptimalSolution() {
		return null;
	}

	@Override
	public double getHVR(Set<Result> results) {
		return 1;
	}

}
